from flask import Flask, request, jsonify, render_template, session, send_file
from flask_sqlalchemy import SQLAlchemy
from flask_jwt_extended import JWTManager, create_access_token, jwt_required, get_jwt_identity
from werkzeug.security import generate_password_hash, check_password_hash
from werkzeug.utils import secure_filename
import os
import uuid
import datetime
import numpy as np
from PIL import Image
import tensorflow as tf
from tensorflow.keras.models import load_model
from flask_cors import CORS

# 初始化Flask应用
app = Flask(__name__)
CORS(app)  # 启用CORS支持跨域请求

# 配置应用
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///plant_database.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['JWT_SECRET_KEY'] = 'your-secret-key-here'  # 用于JWT签名的密钥
app.config['UPLOAD_FOLDER'] = 'uploads'
app.config['MAX_CONTENT_LENGTH'] = 5 * 1024 * 1024  # 5MB文件大小限制

# 初始化数据库和JWT管理器
db = SQLAlchemy(app)
jwt = JWTManager(app)

# 创建上传文件夹
if not os.path.exists(app.config['UPLOAD_FOLDER']):
    os.makedirs(app.config['UPLOAD_FOLDER'])

# 定义数据模型
class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True, nullable=False)
    email = db.Column(db.String(120), unique=True, nullable=False)
    password_hash = db.Column(db.String(128), nullable=False)
    created_at = db.Column(db.DateTime, default=datetime.datetime.utcnow)
    plants = db.relationship('UserPlant', backref='user', lazy=True)
    
    def set_password(self, password):
        self.password_hash = generate_password_hash(password)
    
    def check_password(self, password):
        return check_password_hash(self.password_hash, password)

class Plant(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(80), nullable=False)
    scientific_name = db.Column(db.String(120))
    category = db.Column(db.String(50))
    description = db.Column(db.Text)
    care_instructions = db.Column(db.Text)
    image_url = db.Column(db.String(200))
    difficulty = db.Column(db.Integer)  # 1-5, 1为最简单
    created_at = db.Column(db.DateTime, default=datetime.datetime.utcnow)

class UserPlant(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    plant_id = db.Column(db.Integer, db.ForeignKey('plant.id'), nullable=False)
    nickname = db.Column(db.String(80))
    acquired_date = db.Column(db.DateTime, default=datetime.datetime.utcnow)
    notes = db.Column(db.Text)
    plant = db.relationship('Plant', backref='user_plants')

class PlantRecognitionHistory(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
    image_url = db.Column(db.String(200))
    result = db.Column(db.JSON)
    confidence = db.Column(db.Float)
    created_at = db.Column(db.DateTime, default=datetime.datetime.utcnow)

# 加载植物识别模型
def load_plant_model():
    global model
    model = load_model('plant_model.h5')  # 假设模型文件已存在
    print('模型加载成功')

# 预处理图像用于模型预测
def preprocess_image(image_path):
    img = Image.open(image_path).convert('RGB')
    img = img.resize((224, 224))  # 模型输入尺寸
    img_array = np.array(img)
    img_array = np.expand_dims(img_array, axis=0)
    img_array = img_array / 255.0  # 归一化
    return img_array

# 植物识别API
@app.route('/api/identify', methods=['POST'])
@jwt_required(optional=True)
def identify_plant():
    if 'image' not in request.files:
        return jsonify({'error': '未上传图片'}), 400
    
    file = request.files['image']
    
    if file.filename == '':
        return jsonify({'error': '没有选择图片'}), 400
    
    if file:
        # 生成唯一文件名
        filename = secure_filename(str(uuid.uuid4()) + '.' + file.filename.rsplit('.', 1)[1].lower())
        file_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
        file.save(file_path)
        
        try:
            # 预处理图像并进行预测
            processed_image = preprocess_image(file_path)
            predictions = model.predict(processed_image)
            
            # 获取预测结果
            class_names = ['绿萝', '多肉植物', '蝴蝶兰', '薄荷', '富贵竹', '仙人掌', '吊兰', '常春藤', '芦荟', '虎皮兰']  # 假设的类别
            predicted_class = np.argmax(predictions[0])
            confidence = float(predictions[0][predicted_class])
            
            # 获取植物详细信息
            plant = Plant.query.filter_by(name=class_names[predicted_class]).first()
            
            result = {
                'name': class_names[predicted_class],
                'confidence': confidence,
                'plant_info': plant.to_dict() if plant else None,
                'image_url': f'/uploads/{filename}'
            }
            
            # 记录识别历史（如果用户已登录）
            current_user = get_jwt_identity()
            if current_user:
                user = User.query.filter_by(username=current_user).first()
                if user:
                    history = PlantRecognitionHistory(
                        user_id=user.id,
                        image_url=result['image_url'],
                        result=result,
                        confidence=confidence
                    )
                    db.session.add(history)
                    db.session.commit()
            
            return jsonify(result), 200
            
        except Exception as e:
            print(f"Error during prediction: {str(e)}")
            return jsonify({'error': '识别过程中发生错误'}), 500

# 用户注册API
@app.route('/api/register', methods=['POST'])
def register():
    data = request.get_json()
    
    username = data.get('username')
    email = data.get('email')
    password = data.get('password')
    
    if not username or not email or not password:
        return jsonify({'error': '缺少必要字段'}), 400
    
    if User.query.filter_by(username=username).first():
        return jsonify({'error': '用户名已存在'}), 400
    
    if User.query.filter_by(email=email).first():
        return jsonify({'error': '邮箱已被注册'}), 400
    
    user = User(username=username, email=email)
    user.set_password(password)
    
    db.session.add(user)
    db.session.commit()
    
    return jsonify({'message': '注册成功'}), 201

# 用户登录API
@app.route('/api/login', methods=['POST'])
def login():
    data = request.get_json()
    
    username = data.get('username')
    password = data.get('password')
    
    user = User.query.filter_by(username=username).first()
    
    if not user or not user.check_password(password):
        return jsonify({'error': '用户名或密码错误'}), 401
    
    # 创建JWT令牌
    access_token = create_access_token(identity=user.username)
    
    return jsonify({
        'access_token': access_token,
        'user': {
            'id': user.id,
            'username': user.username,
            'email': user.email
        }
    }), 200

# 获取植物列表API
@app.route('/api/plants', methods=['GET'])
def get_plants():
    category = request.args.get('category')
    page = request.args.get('page', 1, type=int)
    per_page = request.args.get('per_page', 10, type=int)
    
    query = Plant.query
    
    if category:
        query = query.filter_by(category=category)
    
    plants = query.paginate(page=page, per_page=per_page, error_out=False)
    
    result = {
        'plants': [plant.to_dict() for plant in plants.items],
        'total': plants.total,
        'pages': plants.pages,
        'current_page': page
    }
    
    return jsonify(result), 200

# 获取单个植物详情API
@app.route('/api/plants/<int:plant_id>', methods=['GET'])
def get_plant(plant_id):
    plant = Plant.query.get_or_404(plant_id)
    return jsonify(plant.to_dict()), 200

# AI植物生长模拟API
@app.route('/api/simulate', methods=['POST'])
@jwt_required
def simulate_plant_growth():
    data = request.get_json()
    
    plant_id = data.get('plant_id')
    temperature = data.get('temperature')
    humidity = data.get('humidity')
    light_intensity = data.get('light_intensity')
    duration = data.get('duration')  # 周/月/季度
    
    plant = Plant.query.get_or_404(plant_id)
    
    # 这里应该是复杂的AI模型预测
    # 简化模拟，返回示例数据
    growth_prediction = {
        'plant_id': plant_id,
        'plant_name': plant.name,
        'duration': duration,
        'start_date': datetime.datetime.now().strftime('%Y-%m-%d'),
        'end_date': (datetime.datetime.now() + datetime.timedelta(days=duration*7)).strftime('%Y-%m-%d'),
        'growth_stages': [
            {
                'stage': '萌芽期',
                'description': '植物开始发芽，新叶出现',
                'expected_date': (datetime.datetime.now() + datetime.timedelta(days=duration*2)).strftime('%Y-%m-%d'),
                'image_url': f'https://picsum.photos/id/{plant_id*10}/400/300'
            },
            {
                'stage': '生长期',
                'description': '植物快速生长，叶片增多',
                'expected_date': (datetime.datetime.now() + datetime.timedelta(days=duration*4)).strftime('%Y-%m-%d'),
                'image_url': f'https://picsum.photos/id/{plant_id*10+1}/400/300'
            },
            {
                'stage': '成熟期',
                'description': '植物达到成熟状态，可能开花结果',
                'expected_date': (datetime.datetime.now() + datetime.timedelta(days=duration*6)).strftime('%Y-%m-%d'),
                'image_url': f'https://picsum.photos/id/{plant_id*10+2}/400/300'
            }
        ],
        'care_suggestions': [
            f"保持温度在 {temperature-5}°C 至 {temperature+5}°C 之间",
            f"湿度维持在 {humidity-10}% 至 {humidity+10}%",
            f"根据光照强度调整位置，避免过强或过弱的光线",
            f"建议每 {duration*2} 天浇水一次"
        ]
    }
    
    return jsonify(growth_prediction), 200

# 为模型添加to_dict方法以便于JSON序列化
def to_dict(self):
    return {
        'id': self.id,
        'name': self.name,
        'scientific_name': self.scientific_name,
        'category': self.category,
        'description': self.description,
        'care_instructions': self.care_instructions,
        'image_url': self.image_url,
        'difficulty': self.difficulty,
        'created_at': self.created_at.strftime('%Y-%m-%d %H:%M:%S')
    }

# 为模型添加to_dict方法
Plant.to_dict = to_dict

# 上传文件访问路由
@app.route('/uploads/<filename>')
def uploaded_file(filename):
    return send_file(os.path.join(app.config['UPLOAD_FOLDER'], filename))

# 初始化数据库
@app.before_first_request
def create_tables():
    db.create_all()
    # 初始化一些示例数据
    if Plant.query.count() == 0:
        init_plants = [
            Plant(
                name="绿萝",
                scientific_name="Epipremnum aureum",
                category="室内植物",
                description="绿萝是一种常见的室内观叶植物，具有净化空气的功能。",
                care_instructions="保持土壤湿润但不过湿，避免阳光直射，适宜温度15-25°C。",
                image_url="https://picsum.photos/id/106/400/300",
                difficulty=2
            ),
            Plant(
                name="多肉植物",
                scientific_name="Succulent plant",
                category="多肉植物",
                description="多肉植物是一类具有肉质组织的植物，能够储存水分，适应干旱环境。",
                care_instructions="喜欢阳光充足但需避免夏季暴晒，浇水要少，保持土壤干燥。",
                image_url="https://picsum.photos/id/110/400/300",
                difficulty=3
            ),
            Plant(
                name="蝴蝶兰",
                scientific_name="Phalaenopsis aphrodite",
                category="观花植物",
                description="蝴蝶兰是一种常见的观赏兰花，因其花朵形似蝴蝶而得名。",
                care_instructions="保持温暖湿润，避免冷风直吹，使用透气性好的介质，如树皮。",
                image_url="https://picsum.photos/id/111/400/300",
                difficulty=4
            )
        ]
        db.session.add_all(init_plants)
        db.session.commit()

# 启动应用
if __name__ == '__main__':
    load_plant_model()  # 加载模型
    app.run(debug=True)
